<template>
  <div class="h-100 w-100" @mousedown="beginBoxSelect" @mousemove="boxMousemove" @mouseup="boxMouseup">
    <div class="h-100 w-100" :style="`position: relative;background-image: url(${require('../assets/images/bg20.gif')});`" @contextmenu.prevent="showRightMenu" @click.stop="click">
      <svg id="lbpmSvg" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" version="1.1" width="100%" height="100%" style="overflow: auto;" @mousemove="mousemove($event)" @mouseup="mouseup($event)">
        <g id="lbpmG1001">
          <defs id="lbpmDefs1000">
            <marker id="lbpmArrow#999999" viewBox="0 0 20 20" refX="17px" refY="10px" markerUnits="strokeWidth" markerWidth="4px" markerHeight="4px" orient="auto">
              <path id="lbpmPath1017" d="M 0 0 L 20 10 L 0 20 z" fill="#999999" stroke="#999999" stroke-width="1px"></path>
            </marker>
            <marker id="lbpmArrow#999998" viewBox="0 0 20 20" refX="17px" refY="10px" markerUnits="strokeWidth" markerWidth="4px" markerHeight="4px" orient="auto">
              <path id="lbpmPath1082" d="M 0 0 L 20 10 L 0 20 z" fill="#999998" stroke="#999998" stroke-width="1px"></path>
            </marker>
            <marker id="lbpmArrow#FF4444" viewBox="0 0 20 20" refX="17px" refY="10px" markerUnits="strokeWidth" markerWidth="4px" markerHeight="4px" orient="auto">
              <path id="lbpmPath1449" d="M 0 0 L 20 10 L 0 20 z" fill="#FF4444" stroke="#FF4444" stroke-width="1px"></path>
            </marker>
            <marker id="lbpmArrow#444444" viewBox="0 0 20 20" refX="17px" refY="10px" markerUnits="strokeWidth" markerWidth="4px" markerHeight="4px" orient="auto">
              <path id="lbpmPath1965" d="M 0 0 L 20 10 L 0 20 z" fill="#444444" stroke="#444444" stroke-width="1px"></path>
            </marker>
          </defs>
          <!-- <g id="lbpmG1002">
          <g id="lbpmG1003"></g>
          <g id="lbpmG1004"></g>
          <g id="lbpmG1005"></g>
          <rect id="lbpmRect1006" width="20" height="20" fill="#f5f5f5" x="0" y="0" stroke="#d4d4dc" stroke-width="1"></rect>
          <g id="lbpmG1007" transform="translate(20,0)">
            <image id="lbpmImage1008" xlink:href="/static/images/editNode/laneAdd.png" width="20" height="20" style="cursor:pointer;"></image>
          </g>
          <g id="lbpmG1009" transform="translate(0,20)">
            <image id="lbpmImage1010" xlink:href="/static/images/editNode/laneAdd.png" width="20" height="20" style="cursor:pointer;"></image>
          </g>
        </g> -->

          <!-- 节点 -->
          <g id="lbpmG1011">
            <g v-for="(item,index) in nodeData" :ref="index" :key="index" id="lbpmG1021" :transform="item.translate | XYtoTranslate" @click="select(index)" @mousedown="mousedown($event,'nodeData',index)">
              <rect v-if="item.type.key==='rect'" id="lbpmRect1022" width="120" :height="40" class="node_main" :rx="item.type.rx" :ry="item.type.ry" :stroke="activenodeIndex===index||boxSelectNodes.some(key=>key==index)?'#ff4444':'#000000'" fill="#ffffff"></rect>
              <polygon v-else-if="item.type.key==='polygon'" id="lbpmPolygon1041" points="60, 0 120, 40 60, 80 0, 40" transform="translate(0,0)" :stroke="activenodeIndex===index||boxSelectNodes.some(key=>key==index)?'#ff4444':'#000000'" :fill="'#ffffff'"></polygon>
              <image id="lbpmImage1023" :xlink:href="item.image.src" :width="item.image.width" :height="item.image.height" :x="item.image.x" :y="item.image.y"></image>
              <text id="lbpmText1024" :class="'round_nodetb'" :fill="'#000000'" :x="item.type.key==='rect'?72.5:60" :y="item.type.key==='rect'?12.9921875:32.9921875" :font-size="item.text.fontSize" :text-anchor="item.text.textAnchor">
                <tspan v-for="(span,index) in item.text.tspan" :key="'tspan'+index" id="lbpmTspan1026" class="text" :dy="span.dy" :x="span.x">{{span.label}}</tspan>
              </text>
            </g>
          </g>

          <!-- 线 -->
          <g id="lbpmG1012">
            <g id="lbpmG1014" v-show="startLine.length>0">
              <polyline id="lbpmPolyline1015" :points="dottedLine" transform="translate(0,0)" class="line_opt" fill="none" stroke="#999999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" :marker-end="selectedNode.type=='linePointTranslate'&&selectedNode.dragIndex==0?'':'url(#lbpmArrow#999999)'" stroke-dasharray="20, 10"></polyline>
              <polyline id="lbpmPolyline1018" :points="dottedLine" transform="translate(0,0)" class="line_opt" fill="none" stroke="rgba(0,0,0,0)" stroke-width="20"></polyline>
            </g>
            <g id="lbpmG1076" v-for="(line,index) in solidLine" :key="'Polyline'+index" @click="selectline(index)">
              <polyline id="lbpmPolyline1077" :points="line" transform="translate(0,0)" class="line_normal" fill="none" :stroke="index===activelineIndex||boxSelectLines.some(key=>key==index)?'#ff4444':'#999999'" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" :marker-end="index===activelineIndex||boxSelectLines.some(key=>key==index)?'url(#lbpmArrow#FF4444)':'url(#lbpmArrow#999999)'"></polyline>
              <polyline id="lbpmPolyline1078" :points="line" transform="translate(0,0)" class="line_normal" fill="none" stroke="rgba(0,0,0,0)" stroke-width="20"></polyline>
              <text id="lbpmText1079" style="font-size:12;font-family:Helvetica, Arial, sans-serif;text-anchor:start;textLength:1;display:none;" class="line_text text" fill="#000000" font-size="12">
                <tspan id="lbpmTspan1080" dy="11.080000007999999" x="0" style="font-size:12;font-family:Helvetica, Arial, sans-serif;text-anchor:start;textLength:1;"></tspan>
              </text>
            </g>
          </g>

          <!-- 点 -->
          <g id="lbpmG1013">
            <g id="lbpmG1019" v-if="handlePoint&&point &&point.hasOwnProperty('x')">
              <ellipse id="lbpmEllipse1020" :transform="point | XYtoTranslate" rx="4" ry="4" cx="4" cy="4" class="point_main" stroke="#0000ff" fill="#9999ff"></ellipse>
            </g>
            <g id="lbpmG1187" v-for="(item,index) in linePointTranslate" :key="'point'+index" :transform="item | XYtoTranslate" @mousedown.stop="mousedown($event,'linePointTranslate',index)">
              <ellipse id="lbpmEllipse1188" rx="4" ry="4" cx="4" cy="4" class="point_main" stroke="#0000ff" fill="#00ff00" title="双击拐点可删除该拐点">
                <set attributeName="fill" from="lightgrey" to="#ff0000" begin="mouseenter" end="mouseleave" />
              </ellipse>
            </g>
          </g>
        </g>

        <g id="lbpmG1980" v-if="insideIndex!=undefined&&insideIndex!=0&&insideIndex!=1&&nodeData[insideIndex].type.key!='polygon' ">
          <rect id="lbpmRect1981" width="120" height="40" fill="blue" :x="nodeData[insideIndex].translate.x" :y="nodeData[insideIndex].translate.y-38" opacity="0"></rect>
          <polygon id="lbpmPolygon1982" points="8,0 0,10 16,10" :transform="`translate(${nodeData[insideIndex].translate.x+52},${nodeData[insideIndex].translate.y-15}) translate(0,0)`" stroke="#58c0ee" fill="#58c0ee" @mouseover="showAddPreNodeMenu"></polygon>
          <g id="lbpmG1983" v-show="addPreNodeMenuSW">
            <image id="lbpmImage1984" xlink:href="../assets/images/editNode/buttonbar-1_02-02.png" width="16" height="16" :x="nodeData[insideIndex].translate.x" :y="nodeData[insideIndex].translate.y-35" @click="addPreNode('signNode',insideIndex)"></image>
            <image id="lbpmImage1985" xlink:href="../assets/images/editNode/buttonbar-1_02.png" width="16" height="16" :x="nodeData[insideIndex].translate.x+52" :y="nodeData[insideIndex].translate.y-35" @click="addPreNode('reviewNode',insideIndex)"></image>
            <image id="lbpmImage1986" xlink:href="../assets/images/editNode/buttonbar-1_02-03.png" width="16" height="16" :x="nodeData[insideIndex].translate.x+104" :y="nodeData[insideIndex].translate.y-35" @click="addPreNode('sendNode',insideIndex)"></image>
          </g>
        </g>
        <g id="lbpmG1987" v-if="insideIndex!=undefined&&insideIndex!=0&&insideIndex!=2&&nodeData[insideIndex].type.key!='polygon'">
          <rect id="lbpmRect1988" width="120" height="40" fill="blue" :x="nodeData[insideIndex].translate.x" :y="nodeData[insideIndex].translate.y+38" opacity="0"></rect>
          <polygon id="lbpmPolygon1989" points="0,0 16,0 8,10" :transform="`translate(${nodeData[insideIndex].translate.x+52},${nodeData[insideIndex].translate.y+45}) translate(0,0)`" stroke="#58c0ee" fill="#58c0ee" @mouseover="showAddNextNodeMenu"></polygon>
          <g id="lbpmG1990" v-show="addNextNodeMenuSW">
            <image id="lbpmImage1991" xlink:href="../assets/images/editNode/buttonbar-1_02-02.png" width="16" height="16" :x="nodeData[insideIndex].translate.x" :y="nodeData[insideIndex].translate.y+60" @click="addNextNode('signNode',insideIndex)"></image>
            <image id="lbpmImage1992" xlink:href="../assets/images/editNode/buttonbar-1_02.png" width="16" height="16" :x="nodeData[insideIndex].translate.x+52" :y="nodeData[insideIndex].translate.y+60" @click="addNextNode('reviewNode',insideIndex)"></image>
            <image id="lbpmImage1993" xlink:href="../assets/images/editNode/buttonbar-1_02-03.png" width="16" height="16" :x="nodeData[insideIndex].translate.x+104" :y="nodeData[insideIndex].translate.y+60" @click="addNextNode('sendNode',insideIndex)"></image>
          </g>
        </g>

        <defs>
          <filter id="filter" x="0" y="0">
            <feOffset dx="3" dy="2"></feOffset>
            <feGaussianBlur stdDeviation="2"></feGaussianBlur>
            <feColorMatrix type="matrix" values="0.2 0 0 0 0 0 0.2 0 0 0 0 0 0.2 0 0 0 0 0 1 0" result="shadow"></feColorMatrix>
            <feMerge>
              <feMergeNode in="shadow"></feMergeNode>
              <feMergeNode in="SourceGraphic"></feMergeNode>
            </feMerge>
          </filter>
        </defs>
      </svg>
      <table class="rightmenu_main" v-if='rightMenuSwitch' :style="'left:'+left+'px;top:'+top+'px;position: absolute;'">
        <tbody>
          <tr v-for="(item,index) in mainMenu" :key="index">
            <td nowrap="" title="" :class="'children' in item&&item.children.length>0&&hoverIndex==index?'rightmenu_select':'rightmenu_nor'" @mouseover="handleMenu(index)">
              <table border="0" cellpadding="0" cellspacing="0" width="100%" height="100%">
                <tbody>
                  <tr>
                    <td width="10px" :class="'children' in item&&item.children.length>0?'':'rightmenu_check'"></td>
                    <td nowrap="">{{item.label}}</td>
                    <td v-if="item.accelerator" style="text-align:right;padding-right:10px" nowrap="">{{item.accelerator}}</td>
                    <td v-else style="text-align:right" width="10">{{'children' in item&&item.children.length>0?'»':''}}</td>
                    <div v-if="'children' in item&&item.children.length>0&&hoverIndex==index" class="rightmenu_main" :style="'left:179px;top:'+index*22+'px;position: absolute;'">
                      <div v-for="(child,index) in item.children" :key="index" class="d-flex w-100 ai-center rightmenu_child">
                        <div style="padding-left: 10px;">{{child.label}}</div>
                        <div style="padding-right: 10px;flex: 1;display: flex;justify-content: flex-end;">{{child.accelerator}}</div>
                      </div>
                    </div>
                  </tr>
                </tbody>
              </table>
            </td>
          </tr>
        </tbody>
      </table>
      <div class="select_area" v-if="boxSelectStyle" :style="`left: ${boxSelectStyle.left}px; top: ${boxSelectStyle.top}px; width: ${boxSelectStyle.width}px; height: ${boxSelectStyle.height}px;`"></div>
    </div>
  </div>
</template>

<script>
import nodeSvg from "./nodeSvg";
import utils from "./utils";
export default {
  props: {
    editKey: String
  },

  filters: {
    XYtoTranslate: function(obj) {
      return `translate(${obj.x},${obj.y})`;
    }
  },

  data() {
    let _this = this;
    return {
      left: "",
      top: "",
      rightMenuSwitch: false,
      dragging: false,
      hoverIndex: undefined,
      mousePos: { x: 0, y: 0 },
      nodeData: [],
      insideIndex: undefined,
      addPreNodeMenuSW: false,
      addNextNodeMenuSW: false,
      selectedNode: {},
      selectedNodes: {},
      activelineIndex: undefined,
      activenodeIndex: undefined,
      boxSelectNodes: [],
      boxSelectLines: [],
      hoverPointIndex: undefined,
      point: {},
      startLine: [],
      nextLine: {},
      preLine: {},
      linePoints: [],
      solidLineDict: {},
      solidLineRetrieval: [],
      linePointTranslate: [],
      handlePoint: false,
      //这部分是多选的变量
      boxSelectStartPoint: {},
      boxSelectMovePoint: {},
      mousePoint: { x: 0, y: 0 },
      mainMenu: [
        {
          label: "添加",
          key: "add",
          disable: false,
          children: [
            {
              label: "连线",
              accelerator: "W"
            },
            {
              label: "审批节点",
              accelerator: "A"
            },
            {
              label: "签字节点",
              accelerator: "S"
            },
            {
              label: "抄送节点",
              accelerator: "D"
            },
            {
              label: "机器人节点",
              accelerator: "C"
            },
            {
              label: "启动子流程节点",
              accelerator: "P"
            },
            {
              label: "回收子流程节点",
              accelerator: "R"
            },
            {
              label: "人工决策",
              accelerator: "Z"
            },
            {
              label: "条件分支",
              accelerator: "X"
            },
            {
              label: "并行节点",
              accelerator: "B"
            },
            {
              label: "投票节点",
              accelerator: "V"
            },
            {
              label: "检查节点",
              accelerator: "E"
            },
            {
              label: "快捷添加审批节点",
              accelerator: "Shift+Q"
            }
          ]
        },
        {
          label: "属性",
          key: "attribute",
          accelerator: "双击/Enter",
          disable: false,
          children: []
        },
        {
          label: "拷贝",
          key: "copy",
          accelerator: "Ctrl/Shift+C",
          disable: false,
          children: []
        },
        {
          label: "粘贴",
          key: "shift",
          accelerator: "Ctrl/Shift+V",
          disable: false,
          children: []
        },
        {
          label: "删除",
          key: "delect",
          accelerator: "Delete",
          disable: false,
          children: []
        },
        {
          label: "选定",
          key: "select",
          accelerator: "",
          disable: false,
          children: [
            {
              label: "选定所有",
              accelerator: "Ctrl+A"
            },
            {
              label: "所有不选",
              accelerator: "Ctrl+D"
            },
            {
              label: "所有节点",
              accelerator: "Shift+N"
            },
            {
              label: "所有连线",
              accelerator: "Shift+L"
            }
          ]
        },
        {
          label: "显示",
          key: "show",
          accelerator: "",
          disable: false,
          children: [
            {
              label: "放大画布",
              accelerator: "Shift+↓"
            },
            {
              label: "缩小画布",
              accelerator: "Shift+↑"
            },
            {
              label: "放大比例",
              accelerator: "Shift+上滚轮"
            },
            {
              label: "缩小比例",
              accelerator: "Shift+下滚轮"
            },
            {
              label: "还原显示比例",
              accelerator: "Shift+R"
            },
            {
              label: "全屏",
              accelerator: "Shift+M"
            }
          ]
        },
        {
          label: "显示大图标",
          key: "showIcon",
          accelerator: "",
          disable: false,
          children: []
        },
        {
          label: "格式化连线",
          key: "format",
          accelerator: "Shift+T",
          disable: false,
          children: []
        },
        {
          label: "流程检测",
          key: "test",
          accelerator: "Shift+K",
          disable: false,
          children: []
        },
        {
          label: "快捷键说明",
          key: "explain",
          accelerator: "Shift+H",
          disable: false,
          children: []
        }
      ],

      editFun: {
        select: () => {},
        line: () => {},
        reviewNode: (x, y) => {
          _this.nodeData.push(nodeSvg.reviewNode({ x: x - 60, y: y - 20 }));
        },
        signNode: (x, y) => {
          _this.nodeData.push(nodeSvg.signNode({ x: x - 60, y: y - 20 }));
        },
        sendNode: (x, y) => {
          _this.nodeData.push(nodeSvg.sendNode({ x: x - 60, y: y - 20 }));
        },
        robotNode: (x, y) => {
          _this.nodeData.push(nodeSvg.robotNode({ x: x - 60, y: y - 20 }));
        },
        startSubProcessNode: (x, y) => {
          _this.nodeData.push(
            nodeSvg.startSubProcessNode({ x: x - 60, y: y - 20 })
          );
        },
        recoverSubProcessNode: (x, y) => {
          _this.nodeData.push(
            nodeSvg.recoverSubProcessNode({ x: x - 60, y: y - 20 })
          );
        },
        manualBranchNode: (x, y) => {
          _this.nodeData.push(
            nodeSvg.manualBranchNode({ x: x - 60, y: y - 40 })
          );
        },
        autoBranchNode: (x, y) => {
          _this.nodeData.push(nodeSvg.autoBranchNode({ x: x - 60, y: y - 40 }));
        },
        splitJoinNode: (x, y) => {
          // _this.nodeData.push(nodeSvg.splitJoinNode({ x: x - 60, y: y - 40 }));
        },
        voteNode: (x, y) => {
          _this.nodeData.push(nodeSvg.voteNode({ x: x - 60, y: y - 20 }));
        },
        checkNode: (x, y) => {
          _this.nodeData.push(nodeSvg.checkNode({ x: x - 60, y: y - 20 }));
        },
        freeSubFlowNode: (x, y) => {
          _this.nodeData.push(
            nodeSvg.freeSubFlowNode({ x: x - 60, y: y - 20 })
          );
        },
        embeddedSubFlowNode: (x, y) => {
          _this.nodeData.push(
            nodeSvg.embeddedSubFlowNode({ x: x - 60, y: y - 20 })
          );
        },
        adHocSubFlowNode: (x, y) => {
          _this.nodeData.push(
            nodeSvg.adhocSubFlowNode({ x: x - 60, y: y - 20 })
          );
        },
        quickaddreviewnode: (x, y) => {
          _this.nodeData.push(
            nodeSvg.quickaddreviewnode({ x: x - 60, y: y - 20 })
          );
        },
        flowSimulation: (x, y) => {
          _this.nodeData.push(nodeSvg.flowSimulation({ x: x - 60, y: y - 20 }));
        }
      }
    };
  },

  created() {
    let node1 = nodeSvg.startNode({
      x: 340,
      y: 40
    });
    node1.pre = [];
    node1.next = [{ nodeIndex: 1, pointPosition: "U" }];
    let node2 = nodeSvg.draftNode({
      x: 340,
      y: 120
    });
    node2.pre = [{ nodeIndex: 0, pointPosition: "D" }];
    node2.next = [{ nodeIndex: 2, pointPosition: "U" }];
    let node3 = nodeSvg.endNode({
      x: 340,
      y: 360
    });
    node3.pre = [{ nodeIndex: 1, pointPosition: "D" }];
    node3.next = [];
    this.nodeData = [node1, node2, node3];
    this.solidLineDict = {
      0: [
        [
          { nodeIndex: 0, x: 400, y: 80 },
          { nodeIndex: 1, x: 400, y: 120 }
        ]
      ],
      1: [
        [
          { nodeIndex: 1, x: 400, y: 160 },
          { nodeIndex: 2, x: 400, y: 360 }
        ]
      ]
    };
  },

  computed: {
    dottedLine() {
      if (this.startLine.length > 0) {
        let points = this.startLine.map(i => `${i.x},${i.y}`).join(" ");
        // if (this.point.hasOwnProperty("x") && this.editKey == "line") {
        //   return points + ` ${this.point.x + 4},${this.point.y + 4}`;
        // } else {
        return points + ` ${this.mousePoint.x},${this.mousePoint.y}`;
        // }
      }
    },
    solidLine: {
      get() {
        let Arr = [];
        for (let i in this.solidLineDict) {
          for (let j of this.solidLineDict[i]) {
            Arr.push(j.map(k => `${k.x},${k.y}`).join(" "));
          }
        }
        return [...new Set(Arr)];
      }
    },

    nodePosition() {
      if (this.nodeData.length > 0) {
        return this.nodeData.map(i => {
          return {
            x: i.translate.x,
            y: i.translate.y,
            type: i.type.key
          };
        });
      }
    },

    boxSelectStyle() {
      if (
        this.boxSelectStartPoint.hasOwnProperty("x") &&
        this.boxSelectMovePoint.hasOwnProperty("y")
      ) {
        let style = {};
        style.width = Math.abs(
          this.boxSelectStartPoint.x - this.boxSelectMovePoint.x
        );
        style.height = Math.abs(
          this.boxSelectStartPoint.y - this.boxSelectMovePoint.y
        );
        style.left =
          this.boxSelectStartPoint.x > this.boxSelectMovePoint.x
            ? this.boxSelectMovePoint.x
            : this.boxSelectStartPoint.x;
        style.top =
          this.boxSelectStartPoint.y > this.boxSelectMovePoint.y
            ? this.boxSelectMovePoint.y
            : this.boxSelectStartPoint.y;
        return style;
      } else {
        return undefined;
      }
    },

    nodeToline() {
      if (this.nodePosition.length > 0) {
        let dict = {};
        for (let [index, node] of this.nodePosition.entries()) {
          let obj = {};
          if (node.type == "rect") {
            obj.U = { x: node.x + 60, y: node.y, nodeIndex: index };
            obj.D = { x: node.x + 60, y: node.y + 40, nodeIndex: index };
            obj.L = { x: node.x, y: node.y + 20, nodeIndex: index };
            obj.R = { x: node.x + 120, y: node.y + 20, nodeIndex: index };
          } else if (node.type == "polygon") {
            obj.U = { x: node.x + 60, y: node.y, nodeIndex: index };
            obj.D = { x: node.x + 60, y: node.y + 80, nodeIndex: index };
            obj.L = { x: node.x, y: node.y + 40, nodeIndex: index };
            obj.R = { x: node.x + 120, y: node.y + 40, nodeIndex: index };
          }
          dict[index] = obj;
        }
        return dict;
      }
    }
  },

  watch: {
    //每个节点与出口线相关联
    nodeData: {
      handler(newVal, oldVal) {
        //更新入口线,即更新上个节点的出口线
        if (
          newVal[this.activenodeIndex] &&
          newVal[this.activenodeIndex].hasOwnProperty("pre") &&
          newVal[this.activenodeIndex].pre.length > 0
        ) {
          let pre = newVal[this.activenodeIndex].pre;
          for (let item of pre) {
            let start = this.nodeToline[item.nodeIndex][item.pointPosition];
            let next = newVal[item.nodeIndex].next;
            let curNext = next.find(i => i.nodeIndex == this.activenodeIndex);
            let end = this.nodeToline[curNext.nodeIndex][curNext.pointPosition];
            let solidArr = JSON.parse(
              JSON.stringify(this.solidLineDict[item.nodeIndex])
            );

            for (let solid of solidArr) {
              if (
                solid[0].x == start.x &&
                solid[0].y == start.y &&
                solid[solid.length - 1].nodeIndex == this.activenodeIndex
              ) {
                solid[solid.length - 1] = end;
              }
            }

            this.$set(this.solidLineDict, item.nodeIndex, solidArr);
          }
        } else if (this.boxSelectNodes.length > 0) {
          for (let activenodeIndex of this.boxSelectNodes) {
            if (
              newVal[activenodeIndex] &&
              newVal[activenodeIndex].hasOwnProperty("pre") &&
              newVal[activenodeIndex].pre.length > 0
            ) {
              let pre = newVal[activenodeIndex].pre;
              for (let item of pre) {
                let start = this.nodeToline[item.nodeIndex][item.pointPosition];
                let next = newVal[item.nodeIndex].next;
                let curNext = next.find(i => i.nodeIndex == activenodeIndex);
                let end = this.nodeToline[curNext.nodeIndex][
                  curNext.pointPosition
                ];
                let solidArr = JSON.parse(
                  JSON.stringify(this.solidLineDict[item.nodeIndex])
                );

                for (let solid of solidArr) {
                  if (
                    solid[0].x == start.x &&
                    solid[0].y == start.y &&
                    solid[solid.length - 1].nodeIndex == activenodeIndex
                  ) {
                    solid[solid.length - 1] = end;
                  }
                }

                this.$set(this.solidLineDict, item.nodeIndex, solidArr);
              }
            }
          }
        }
        //更新出口线
        if (
          newVal[this.activenodeIndex] &&
          newVal[this.activenodeIndex].hasOwnProperty("next") &&
          newVal[this.activenodeIndex].next.length > 0
        ) {
          let next = newVal[this.activenodeIndex].next;
          let solidArr = JSON.parse(
            JSON.stringify(this.solidLineDict[this.activenodeIndex])
          );
          for (let item of next) {
            let end = this.nodeToline[item.nodeIndex][item.pointPosition];
            let pre = newVal[item.nodeIndex].pre;
            let curPre = pre.find(i => i.nodeIndex == this.activenodeIndex);
            let start = this.nodeToline[curPre.nodeIndex][curPre.pointPosition];
            for (let solid of solidArr) {
              if (
                solid[solid.length - 1].x == end.x &&
                solid[solid.length - 1].y == end.y
              ) {
                solid[0] = start;
              }
            }
          }
          this.$set(this.solidLineDict, this.activenodeIndex, solidArr);
        } else if (this.boxSelectNodes.length > 0) {
          for (let activenodeIndex of this.boxSelectNodes) {
            if (
              newVal[activenodeIndex] &&
              newVal[activenodeIndex].hasOwnProperty("next") &&
              newVal[activenodeIndex].next.length > 0
            ) {
              let next = newVal[activenodeIndex].next;
              let solidArr = JSON.parse(
                JSON.stringify(this.solidLineDict[activenodeIndex])
              );
              for (let item of next) {
                let end = this.nodeToline[item.nodeIndex][item.pointPosition];
                let pre = newVal[item.nodeIndex].pre;
                let curPre = pre.find(i => i.nodeIndex == activenodeIndex);
                let start = this.nodeToline[curPre.nodeIndex][
                  curPre.pointPosition
                ];
                for (let solid of solidArr) {
                  if (
                    solid[solid.length - 1].x == end.x &&
                    solid[solid.length - 1].y == end.y
                  ) {
                    solid[0] = start;
                  }
                }
              }
              this.$set(this.solidLineDict, activenodeIndex, solidArr);
            }
          }
        }
      },
      deep: true
    },
    editKey: {
      handler(newVal, oldVal) {
        if (newVal !== "select") {
          this.rightMenuSwitch = false;
          this.nodeData.map(i => {
            i.type.stroke = "#000000";
            return i;
          });
        }

        if (newVal === "line") {
          this.activelineIndex = undefined;
          this.activenodeIndex = undefined;
          this.linePointTranslate = [];
          this.handlePoint = true;
        } else {
          this.handlePoint = false;
          this.startLine = [];
        }
      }
    },
    mousePoint: {
      handler(newVal, oldVal) {
        if (this.startLine.length > 0) {
          this.linePoints = [[newVal.x, newVal.y]];
        }
      },
      deep: true
    },
    activelineIndex: {
      handler(newVal, oldVal) {
        let val = newVal;
        if (
          newVal == undefined &&
          this.selectedNode.type != "linePointTranslate"
        ) {
          this.linePointTranslate = [];
          return;
        } else {
          let Dict = {};
          for (let i in this.solidLineDict) {
            for (let j of this.solidLineDict[i]) {
              j.forEach(k => {
                Dict[`${k.x},${k.y}`] = {
                  x: k.x - 4,
                  y: k.y - 4,
                  nodeIndex: k.nodeIndex
                };
              });
            }
          }
          if (this.solidLine[newVal] != undefined) {
            this.linePointTranslate = this.solidLine[newVal]
              .match(/\d+(,\d+)/g)
              .map(i => Dict[i]);
          }
        }
      }
    },
    boxSelectLines: {
      handler(newVal, oldVal) {
        this.solidLineRetrieval = [];
        //定位solidLineDict具体线,并记录值,该值将用于移动的基础
        let Dict = {};
        for (let i in this.solidLineDict) {
          for (let [index, j] of this.solidLineDict[i].entries()) {
            let position = j.reduce((pre, cur) => {
              return pre + ` ${cur.x},${cur.y}`;
            }, "");
            position = position.trim();
            Dict[position] = { nodekey: i, index: index, line: j };
          }
        }
        let solidLineRetrieval = [];
        for (let val of newVal) {
          solidLineRetrieval.push(Dict[this.solidLine[val]]);
        }

        //如果框进的线头尾连着的节点没有被框选,不需要平移,所以必须过滤掉
        this.solidLineRetrieval = solidLineRetrieval.filter(
          i =>
            this.boxSelectNodes.some(
              j => j == i.line[i.line.length - 1].nodeIndex
            ) && this.boxSelectNodes.some(j => j == i.line[0].nodeIndex)
        );
      },
      deep: true
    }
  },

  methods: {
    isInside(xa, ya, x, y, type) {
      let xb = 0;
      let yb = 0;
      xa = xa - 5;
      ya = ya - 5;
      if (type == "rect") {
        xb = xa + 130;
        yb = ya + 50;
      } else if (type == "polygon") {
        xb = xa + 130;
        yb = ya + 90;
      }

      if (x < xb && x > xa && y < yb && y > ya) {
        return true;
      }
      return false;
    },

    isHideHoverImg(xa, ya, x, y) {
      let xb = 0;
      let yb = 0;
      xa = xa;
      ya = ya - 40;
      xb = xa + 125;
      yb = ya + 120;

      if (x < xb && x > xa && y < yb && y > ya) {
        return false;
      }
      return true;
    },

    showAddPreNodeMenu() {
      this.addPreNodeMenuSW = true;
      this.addNextNodeMenuSW = false;
    },

    showAddNextNodeMenu() {
      this.addNextNodeMenuSW = true;
      this.addPreNodeMenuSW = false;
    },

    surfaceInBox(translate, type) {
      if (this.boxSelectStyle != undefined) {
        let arr = [];
        if (type == "rect") {
          arr = [
            { x: translate.x, y: translate.y },
            { x: translate.x + 120, y: translate.y },
            { x: translate.x, y: translate.y + 40 },
            { x: translate.x + 120, y: translate.y + 40 }
          ];
        } else if (type == "polygon") {
          arr = [
            { x: translate.x, y: translate.y },
            { x: translate.x + 120, y: translate.y + 80 },
            { x: translate.x, y: translate.y },
            { x: translate.x + 120, y: translate.y + 80 }
          ];
        }
        let edgexa = this.boxSelectStyle.left;
        let edgexb = this.boxSelectStyle.left + this.boxSelectStyle.width;
        let edgeya = this.boxSelectStyle.top;
        let edgeyb = this.boxSelectStyle.top + this.boxSelectStyle.height;

        let res = true;
        for (let element of arr) {
          if (
            element.x > edgexb ||
            element.x < edgexa ||
            element.y > edgeyb ||
            element.y < edgeya
          ) {
            res = false;
            break;
          }
        }

        return res;
      }
    },

    lineInBox(points) {
      if (this.boxSelectStyle != undefined) {
        let arr = points.split(" ");
        arr = arr.map(i => {
          let point = i.split(",");
          return { x: ~~point[0], y: ~~point[1] };
        });
        let edgexa = this.boxSelectStyle.left;
        let edgexb = this.boxSelectStyle.left + this.boxSelectStyle.width;
        let edgeya = this.boxSelectStyle.top;
        let edgeyb = this.boxSelectStyle.top + this.boxSelectStyle.height;
        let res = true;
        for (let element of arr) {
          if (
            element.x > edgexb ||
            element.x < edgexa ||
            element.y > edgeyb ||
            element.y < edgeya
          ) {
            res = false;
            break;
          }
        }
        return res;
      }
    },

    showRightMenu(event) {
      if (this.editKey === "select") {
        this.left = event.layerX;
        this.top = event.layerY;
        this.hoverIndex = undefined;
        this.$nextTick(() => {
          this.rightMenuSwitch = true;
        });
      } else {
        this.$emit("resetEdit");
      }
    },

    handleMenu(index) {
      this.hoverIndex = index;
    },

    click(e) {
      const event = window.event || e;
      let x = this.benchmark(event.offsetX);
      let y = this.benchmark(event.offsetY);
      this.rightMenuSwitch = false;
      this.hoverIndex = undefined;
      //其他模式下添加节点
      if (this.editKey !== "line") {
        if (this.editFun[this.editKey]) {
          this.editFun[this.editKey](x, y);
          this.$emit("resetEdit");
        }
      } else if (this.editKey == "line") {
        //连线模式定义起点虚线连接
        if (this.startLine.length == 0) {
          if (this.point && this.point.hasOwnProperty("x")) {
            this.startLine.push({
              x: this.point.x + 4,
              y: this.point.y + 4,
              nodeIndex: this.point.nodeIndex
            });
            let nextLine = {
              nodeIndex: this.point.nodeIndex,
              type: this.point.type
            };
            let nodePointDict = this.nodeToline[this.point.nodeIndex];
            for (let key in nodePointDict) {
              if (
                nodePointDict[key].x == this.point.x + 4 &&
                nodePointDict[key].y == this.point.y + 4
              ) {
                nextLine.pointPosition = key;
              }
            }
            this.nextLine = nextLine;
            this.point = {};
            this.handlePoint = false;
          }
          //连线模式定义转折点或终点
        } else {
          //终点
          if (this.point && this.point.hasOwnProperty("nodeIndex")) {
            let newSolid = this.startLine.concat({
              x: this.point.x + 4,
              y: this.point.y + 4,
              nodeIndex: this.point.nodeIndex
            });

            if (!this.solidLineDict.hasOwnProperty(this.nextLine.nodeIndex)) {
              this.$set(this.solidLineDict, this.nextLine.nodeIndex, [
                newSolid
              ]);
            } else {
              this.solidLineDict[this.nextLine.nodeIndex].push(newSolid);
            }

            this.preLine = { nodeIndex: this.point.nodeIndex };
            let nodePointDict = this.nodeToline[this.point.nodeIndex];
            for (let key in nodePointDict) {
              if (
                nodePointDict[key].x == this.point.x + 4 &&
                nodePointDict[key].y == this.point.y + 4
              ) {
                this.preLine.pointPosition = key;
              }
            }

            if (
              !this.nodeData[this.nextLine.nodeIndex].hasOwnProperty("next")
            ) {
              this.nodeData[this.nextLine.nodeIndex].next = [];
            }

            this.nodeData[this.nextLine.nodeIndex].next.push(this.preLine);

            if (!this.nodeData[this.point.nodeIndex].hasOwnProperty("pre")) {
              this.nodeData[this.point.nodeIndex].pre = [];
            }

            this.nodeData[this.point.nodeIndex].pre.push(this.nextLine);

            this.point = {};
            this.startLine = [];
          } else {
            //转折点
            this.startLine.push({ x, y });
          }
        }
      }
    },

    mousedown(e, type, dragIndex) {
      this.dragging = true;
      //解决拖动会选中文字的问题
      document.onselectstart = function() {
        return false;
      };
      document.ondragstart = function() {
        return false;
      };
      let position = "";
      if (type == "nodeData") {
        position = this.nodeData[dragIndex].translate;
        this.linePointTranslate = {};
      } else if (type == "linePointTranslate") {
        position = this.linePointTranslate[dragIndex];
      }

      let currentX = position.x;
      let currentY = position.y;
      this.selectedNode = { type, currentX, currentY, dragIndex };
      if (type == "linePointTranslate") {
        this.selectedNode.nodeIndex = position.nodeIndex;
      }
      const event = window.event || e;

      this.mousePos.x = event.clientX;
      this.mousePos.y = event.clientY;
    },

    mousemove: utils._throttle(function(e) {
      //解决拖动会选中文字的问题
      if (this.boxSelectStartPoint.hasOwnProperty("x")) {
        return;
      }
      document.onselectstart = function() {
        return false;
      };
      document.ondragstart = function() {
        return false;
      };
      const event = window.event || e;
      //要么线模式,要么选中线且移动线头或线尾,否则不显示点
      //判断是否进入节点
      let inside = false;
      for (let [index, item] of this.nodePosition.entries()) {
        if (
          this.isInside(
            item.x,
            item.y,
            event.offsetX,
            event.offsetY,
            item.type
          ) == true
        ) {
          inside = true;
          if (
            this.editKey == "select" &&
            Object.keys(this.linePointTranslate).length == 0
          ) {
            this.insideIndex = index;
          }
          // if (
          //   //rect 只有一个出口,polygon 有多个出口
          //   (this.editKey == "line" &&
          //     this.selectedNode.dragIndex == 0 &&
          //     item.type === "rect" &&
          //     this.nodeData[index].next.length > 0) ||
          //   (this.editKey == "line" &&
          //     item.type === "rect" &&
          //     this.nodeData[index].next.length > 0)
          // ) {
          //   break;
          // }
          // 显示点的情况：要么在线模式下，要么在选中线的头或尾端
          if (
            this.editKey == "line" ||
            (this.selectedNode.type == "linePointTranslate" &&
              this.selectedNode.dragIndex == 0 &&
              this.dragging == true) ||
            (this.selectedNode.type == "linePointTranslate" &&
              this.selectedNode.dragIndex ==
                this.linePointTranslate.length - 1 &&
              this.dragging == true)
          ) {
            let datumPoint = {};
            let ellipse = {};
            if (item.type === "polygon") {
              datumPoint = { x: item.x + 60, y: -(item.y + 40) };
              let x = event.offsetX - datumPoint.x;
              let y = -(event.offsetY + datumPoint.y);
              if (x >= 0 && y >= (-1 / 3) * x && y <= (1 / 3) * x) {
                ellipse.x = datumPoint.x + 56;
                ellipse.y = -datumPoint.y - 4;
              } else if (x <= 0 && y <= (-1 / 3) * x && y >= (1 / 3) * x) {
                ellipse.x = datumPoint.x - 64;
                ellipse.y = -datumPoint.y - 4;
              } else if (y >= 0 && x >= -3 * y && x <= 3 * y) {
                ellipse.x = datumPoint.x - 4;
                ellipse.y = -datumPoint.y - 44;
              } else if (y <= 0 && x <= -3 * y && x >= 3 * y) {
                ellipse.x = datumPoint.x - 4;
                ellipse.y = -datumPoint.y + 36;
              }
            } else if (item.type === "rect") {
              datumPoint = { x: item.x + 60, y: -(item.y + 20) };
              let x = event.offsetX - datumPoint.x;
              let y = -(event.offsetY + datumPoint.y);
              if (x >= 0 && y >= (-1 / 3) * x && y <= (1 / 3) * x) {
                ellipse.x = datumPoint.x + 56;
                ellipse.y = -datumPoint.y - 4;
              } else if (x <= 0 && y <= (-1 / 3) * x && y >= (1 / 3) * x) {
                ellipse.x = datumPoint.x - 64;
                ellipse.y = -datumPoint.y - 4;
              } else if (y >= 0 && x >= -3 * y && x <= 3 * y) {
                ellipse.x = datumPoint.x - 4;
                ellipse.y = -datumPoint.y - 24;
              } else if (y <= 0 && x <= -3 * y && x >= 3 * y) {
                ellipse.x = datumPoint.x - 4;
                ellipse.y = -datumPoint.y + 16;
              }
            }

            for (let key in this.nodeToline[index]) {
              if (
                this.nodeToline[index][key].x == ellipse.x + 4 &&
                this.nodeToline[index][key].y == ellipse.y + 4
              ) {
                ellipse.pointPosition = key;
              }
            }

            this.point = {
              x: ellipse.x,
              y: ellipse.y,
              pointPosition: ellipse.pointPosition,
              nodeIndex: index,
              type: item.type
            };
            this.handlePoint = true;
            break;
          } else {
            this.point = {};
          }
        }
      }

      if (inside == false) {
        this.point = {};
        this.handlePoint = false;
      }

      if (this.insideIndex) {
        if (
          this.isHideHoverImg(
            this.nodePosition[this.insideIndex].x,
            this.nodePosition[this.insideIndex].y,
            event.offsetX,
            event.offsetY
          )
        ) {
          this.insideIndex = undefined;
          this.addPreNodeMenuSW = false;
          this.addNextNodeMenuSW = false;
        }
      }

      if (this.editKey === "select") {
        if (
          !this.dragging &&
          Object.keys(this.boxSelectStartPoint).length == 0
        ) {
          return;
        }

        //如果鼠标在节点里则移动节点，或者触发框选
        if (this.selectedNode.type == "nodeData") {
          this.select(this.selectedNode.dragIndex);
        }
        let nx = event.clientX - this.mousePos.x;
        let ny = event.clientY - this.mousePos.y;

        this.reDrag(nx, ny);
      } else if (this.editKey === "line") {
        this.mousePoint.x = event.offsetX;
        this.mousePoint.y = event.offsetY;
      }
    }, 16),

    reDrag(nx, ny) {
      if (
        this.editKey !== "select" &&
        Object.keys(this.boxSelectStartPoint).length == 0
      ) {
        return;
      }
      //框选移动
      if (this.boxSelectNodes.length > 0) {
        for (let [index, i] of this.boxSelectNodes.entries()) {
          this.nodeData[i].translate = {
            x: this.selectedNodes[i].x + nx,
            y: this.selectedNodes[i].y + ny
          };
          for (let item of this.solidLineRetrieval) {
            this.$set(
              this.solidLineDict[item.nodekey],
              item.index,
              item.line.map(i => {
                return {
                  nodeIndex: i.nodeIndex,
                  x: i.x + nx,
                  y: i.y + ny
                };
              })
            );
          }
        }
      } else {
        let selectedNode = this.selectedNode;
        let x = selectedNode.currentX + nx;
        let y = selectedNode.currentY + ny;
        if (selectedNode.type == "nodeData") {
          this.nodeData[selectedNode.dragIndex].translate = { x, y };
        } else if (selectedNode.type == "linePointTranslate") {
          this.$set(this.linePointTranslate, selectedNode.dragIndex, {
            x,
            y
          });

          let solidArr = this.linePointTranslate.map(i => {
            return {
              x: i.x + 4,
              y: i.y + 4,
              nodeIndex: i.nodeIndex
            };
          });

          if (
            selectedNode.dragIndex == this.linePointTranslate.length - 1 ||
            selectedNode.dragIndex == 0
          ) {
            let obj = solidArr[selectedNode.dragIndex];
            this.mousePoint.x = obj.x;
            this.mousePoint.y = obj.y;

            //移动线尾则固定线头,反之亦然
            this.startLine =
              selectedNode.dragIndex == 0
                ? [
                    {
                      x: solidArr[1].x,
                      y: solidArr[1].y,
                      nodeIndex: solidArr[1].nodeIndex
                    }
                  ]
                : [
                    {
                      x: solidArr[this.linePointTranslate.length - 2].x,
                      y: solidArr[this.linePointTranslate.length - 2].y,
                      nodeIndex:
                        solidArr[this.linePointTranslate.length - 2].nodeIndex
                    }
                  ];
          } else {
            let soilds = this.solidLineDict[solidArr[0].nodeIndex];
            let index = soilds.findIndex(
              i =>
                i[i.length - 1].nodeIndex ==
                  solidArr[solidArr.length - 1].nodeIndex &&
                i[0].nodeIndex == solidArr[0].nodeIndex
            );

            this.$set(
              this.solidLineDict[solidArr[0].nodeIndex],
              index,
              solidArr
            );
          }
        }
      }
    },

    mouseup(e) {
      if (this.boxSelectStartPoint.hasOwnProperty("x")) {
        return;
      }
      this.dragging = false;
      let selectedNode = this.selectedNode;
      document.onselectstart = function() {
        return true;
      }; //解决拖动会选中文字的问题
      document.ondragstart = function() {
        return true;
      };

      //节点移动操作
      //框选移动修正
      if (this.boxSelectNodes.length > 0) {
        for (let key of this.boxSelectNodes) {
          this.nodeData[key].translate = {
            x: this.benchmark(this.nodeData[key].translate.x),
            y: this.benchmark(this.nodeData[key].translate.y)
          };
          this.selectedNodes[key] = this.nodeData[key].translate;
        }
        for (let item of this.solidLineRetrieval) {
          this.$set(
            this.solidLineDict[item.nodekey],
            item.index,
            this.solidLineDict[item.nodekey][item.index].map(i => {
              return {
                nodeIndex: i.nodeIndex,
                x: this.benchmark(i.x),
                y: this.benchmark(i.y)
              };
            })
          );
        }

        for (let item of this.solidLineRetrieval) {
          item.line = this.solidLineDict[item.nodekey][item.index];
        }
      } else if (
        selectedNode.hasOwnProperty("dragIndex") &&
        selectedNode.type == "nodeData"
      ) {
        let position = this.nodeData[selectedNode.dragIndex].translate;
        this.nodeData[selectedNode.dragIndex].translate = {
          x: this.benchmark(position.x),
          y: this.benchmark(position.y)
        };
      } else if (
        //线端移动操作
        selectedNode.hasOwnProperty("dragIndex") &&
        selectedNode.type == "linePointTranslate"
      ) {
        let linePointTranslate = JSON.parse(
          JSON.stringify(this.linePointTranslate)
        );
        let solidArr = linePointTranslate.map(i => {
          return {
            x: i.x + 4,
            y: i.y + 4,
            nodeIndex: i.nodeIndex
          };
        });

        //线尾操作
        if (selectedNode.dragIndex == this.linePointTranslate.length - 1) {
          //有节点操作
          if (this.point.hasOwnProperty("nodeIndex")) {
            //前端线调整
            this.$set(this.linePointTranslate, selectedNode.dragIndex, {
              x: this.point.x,
              y: this.point.y,
              nodeIndex: this.point.nodeIndex
            });

            solidArr[selectedNode.dragIndex] = {
              x: this.point.x + 4,
              y: this.point.y + 4,
              nodeIndex: this.point.nodeIndex
            };
            let soilds = this.solidLineDict[solidArr[0].nodeIndex];
            let index = soilds.findIndex(
              i =>
                i[i.length - 1].nodeIndex == selectedNode.nodeIndex &&
                i[0].nodeIndex == solidArr[0].nodeIndex
            );
            this.$set(
              this.solidLineDict[solidArr[0].nodeIndex],
              index,
              solidArr
            );

            //数据结构调整

            let selectNodeIndex = this.selectedNode.nodeIndex; //选择点
            let preNodeIndex = solidArr[0].nodeIndex; //固定线头点
            let curNodeIndex = this.point.nodeIndex; //移动后点
            //移动线头代表选择节点的上一个节点未变,缓存
            let pre = this.nodeData[selectNodeIndex].pre.find(
              i => i.nodeIndex == preNodeIndex
            );

            /* 续接节点pre */

            //删除选择点的pre
            this.nodeData[selectNodeIndex].pre = this.nodeData[
              selectNodeIndex
            ].pre.filter(i => i.nodeIndex != preNodeIndex);
            //移动后点续接pre
            this.nodeData[curNodeIndex].pre = [
              ...this.nodeData[curNodeIndex].pre,
              pre
            ];

            //更替节点next
            let next = {
              nodeIndex: curNodeIndex,
              pointPosition: this.point.pointPosition
            };
            this.nodeData[preNodeIndex].next = this.nodeData[
              preNodeIndex
            ].next.filter(i => i.nodeIndex != curNodeIndex);

            this.nodeData[preNodeIndex].next = [
              ...this.nodeData[preNodeIndex].next,
              next
            ];

            this.startLine = [];
            this.selectedNode.currentX = this.point.x;
            this.selectedNode.currentY = this.point.y;
            this.selectedNode.nodeIndex = curNodeIndex;
          } else {
            //无节点返回
            this.startLine = [];
            this.linePointTranslate[selectedNode.dragIndex] = {
              x: this.selectedNode.currentX,
              y: this.selectedNode.currentY,
              nodeIndex: this.selectedNode.nodeIndex
            };
            return;
          }
          //线头操作
        } else if (selectedNode.dragIndex === 0) {
          if (this.point.hasOwnProperty("nodeIndex")) {
            this.$set(this.linePointTranslate, selectedNode.dragIndex, {
              x: this.point.x,
              y: this.point.y,
              nodeIndex: this.point.nodeIndex
            });

            solidArr[selectedNode.dragIndex] = {
              x: this.point.x + 4,
              y: this.point.y + 4,
              nodeIndex: this.point.nodeIndex
            };

            let soilds = this.solidLineDict[selectedNode.nodeIndex];
            let index = soilds.findIndex(
              i =>
                i[i.length - 1].nodeIndex ==
                  solidArr[solidArr.length - 1].nodeIndex &&
                i[0].nodeIndex == selectedNode.nodeIndex
            );
            //新移动的线头处初始是否有线
            if (this.solidLineDict.hasOwnProperty(solidArr[0].nodeIndex)) {
              //有则推入
              let arr = soilds[index];
              arr[0] = solidArr[0];
              this.solidLineDict[solidArr[0].nodeIndex].push(arr);
            } else {
              //无则新增
              let arr = soilds[index];
              arr[0] = solidArr[0];
              this.$set(this.solidLineDict, solidArr[0].nodeIndex, [arr]);
            }

            //旧移动的线头处删完该线是否还有线,没线整个删除
            this.solidLineDict[selectedNode.nodeIndex].splice(index, 1);
            if (this.solidLineDict[selectedNode.nodeIndex].length == 0) {
              Reflect.deleteProperty(
                this.solidLineDict,
                selectedNode.nodeIndex
              );
            }

            //数据结构调整
            let preIndex = selectedNode.nodeIndex;
            //更替节点next
            let next = this.nodeData[preIndex].next.find(
              i => i.nodeIndex == solidArr[solidArr.length - 1].nodeIndex
            );
            //旧节点删除
            this.nodeData[preIndex].next = this.nodeData[preIndex].next.filter(
              i => i.nodeIndex != solidArr[solidArr.length - 1].nodeIndex
            );
            //新节点增加

            this.nodeData[this.point.nodeIndex].next = [
              ...this.nodeData[this.point.nodeIndex].next,
              next
            ];

            this.nodeData[
              solidArr[solidArr.length - 1].nodeIndex
            ].pre = this.nodeData[
              solidArr[solidArr.length - 1].nodeIndex
            ].pre.map(i => {
              if (i.nodeIndex == preIndex) {
                return {
                  nodeIndex: this.point.nodeIndex,
                  pointPosition: this.point.pointPosition,
                  type: this.point.type
                };
              } else {
                return i;
              }
            });

            this.startLine = [];
            this.selectedNode.currentX = this.point.x;
            this.selectedNode.currentY = this.point.y;
          } else {
            this.startLine = [];
            this.linePointTranslate[selectedNode.dragIndex] = {
              x: this.selectedNode.currentX,
              y: this.selectedNode.currentY,
              nodeIndex: this.selectedNode.nodeIndex
            };
            return;
          }
        } else {
          //折点操作,进行修正
          this.$set(this.linePointTranslate, selectedNode.dragIndex, {
            x:
              this.benchmark(
                this.linePointTranslate[selectedNode.dragIndex].x
              ) - 4,
            y:
              this.benchmark(
                this.linePointTranslate[selectedNode.dragIndex].y
              ) - 4
          });

          solidArr[selectedNode.dragIndex] = {
            x: this.linePointTranslate[selectedNode.dragIndex].x + 4,
            y: this.linePointTranslate[selectedNode.dragIndex].y + 4,
            nodeIndex: this.point.nodeIndex
          };
          let soilds = this.solidLineDict[solidArr[0].nodeIndex];
          let index = soilds.findIndex(
            i =>
              i[i.length - 1].nodeIndex ==
                solidArr[solidArr.length - 1].nodeIndex &&
              i[0].nodeIndex == solidArr[0].nodeIndex
          );

          this.$set(this.solidLineDict[solidArr[0].nodeIndex], index, solidArr);
        }
        this.activelineIndex = undefined;
      }
    },

    handleHoverPoint(index) {
      this.hoverPointIndex = index;
    },

    benchmark(position) {
      return Math.round(position / 20) * 20;
    },

    select(index) {
      if (this.editKey !== "select" || this.boxSelectNodes.length > 0) {
        return;
      }
      this.activenodeIndex = index;
      this.activelineIndex = undefined;
    },

    delect() {
      activelineIndex;
      activenodeIndex;
    },

    selectline(index) {
      if (this.editKey !== "select") {
        return;
      }
      this.activelineIndex = index;
      this.activenodeIndex = undefined;
    },

    beginBoxSelect(e) {
      if (this.editKey == "select") {
        let inside = false;
        const event = window.event || e;
        for (let [index, item] of this.nodePosition.entries()) {
          if (
            this.isInside(
              item.x,
              item.y,
              event.offsetX,
              event.offsetY,
              item.type
            ) == true
          ) {
            inside = true;
            break;
          }
        }
        if (inside == false) {
          this.boxSelectStartPoint = { x: event.offsetX, y: event.offsetY };
          this.diffBox = {
            x: event.clientX - event.offsetX,
            y: event.clientY - event.offsetY
          };
        }
      }
    },

    boxMousemove: utils._throttle(function(e) {
      if (
        this.boxSelectStartPoint.hasOwnProperty("x") &&
        this.editKey == "select"
      ) {
        const event = window.event || e;
        this.boxSelectMovePoint = {
          x: event.clientX - this.diffBox.x,
          y: event.clientY - this.diffBox.y
        };
      }
    }, 16),

    boxMouseup() {
      if (this.boxSelectStartPoint.hasOwnProperty("x")) {
        this.boxSelectNodes = [];
        this.boxSelectLines = [];
        for (let [index, item] of this.nodeData.entries()) {
          if (this.surfaceInBox(item.translate, item.type.key) == true) {
            this.boxSelectNodes.push(index);
          }
        }
        for (let [index, item] of this.solidLine.entries()) {
          if (this.lineInBox(item) == true) {
            this.boxSelectLines.push(index);
          }
        }
        if (this.boxSelectNodes.length > 0) {
          for (let [index, item] of this.boxSelectNodes.entries())
            this.selectedNodes[item] = this.nodeData[item].translate;
        }
        this.activenodeIndex = undefined;
        this.activelineIndex = undefined;
        this.boxSelectStartPoint = {};
        this.boxSelectMovePoint = {};
      }
    },

    addPreNode(type, nodeIndex) {
      let _this = this;
      let curNode = JSON.parse(JSON.stringify(_this.nodeData[nodeIndex]));
      //先暂定为第一条线
      let preNode = JSON.parse(
        JSON.stringify(_this.nodeData[curNode.pre[0].nodeIndex])
      );
      let node = undefined;
      switch (type) {
        case "signNode":
          node = nodeSvg.signNode({
            x: curNode.translate.x,
            y: curNode.translate.y - 80
          });
          break;
        case "reviewNode":
          node = nodeSvg.reviewNode({
            x: curNode.translate.x,
            y: curNode.translate.y - 80
          });
          break;
        case "sendNode":
          node = nodeSvg.sendNode({
            x: curNode.translate.x,
            y: curNode.translate.y - 80
          });
          break;
      }
      //新增节点与旧节点pre,next属性替换
      node.next = preNode.next.filter(i => i.nodeIndex == nodeIndex);
      node.pre = curNode.pre;
      _this.nodeData.push(node);

      _this.nodeData[nodeIndex].pre = [
        { nodeIndex: _this.nodeData.length - 1, pointPosition: "D" }
      ];
      _this.nodeData[curNode.pre[0].nodeIndex].next = _this.nodeData[
        curNode.pre[0].nodeIndex
      ].next.filter(i => i.nodeIndex != nodeIndex);

      _this.nodeData[curNode.pre[0].nodeIndex].next.push({
        nodeIndex: _this.nodeData.length - 1,
        pointPosition: "U"
      });
      //拿一下新节点的UD坐标,新增线
      let uppoint = this.nodeToline[_this.nodeData.length - 1].U;
      let downpoint = this.nodeToline[_this.nodeData.length - 1].D;

      //curSolidIndex 定位下当前节点的上一条线的具体index
      let curSolidIndex = undefined;
      for (let [index, item] of _this.solidLineDict[
        curNode.pre[0].nodeIndex
      ].entries()) {
        if (item.some(j => j.nodeIndex == nodeIndex)) {
          curSolidIndex = index;
        }
      }
      let newLineTail =
        _this.solidLineDict[curNode.pre[0].nodeIndex][curSolidIndex][
          _this.solidLineDict[curNode.pre[0].nodeIndex][curSolidIndex].length -
            1
        ];

      _this.solidLineDict[curNode.pre[0].nodeIndex][curSolidIndex][
        _this.solidLineDict[curNode.pre[0].nodeIndex][curSolidIndex].length - 1
      ] = uppoint;
      _this.$set(_this.solidLineDict, _this.nodeData.length - 1, [
        [downpoint, newLineTail]
      ]);
    },

    addNextNode(type, nodeIndex) {
      let _this = this;
      let curNode = JSON.parse(JSON.stringify(_this.nodeData[nodeIndex]));
      //先暂定为第一条线
      let nextNode = JSON.parse(
        JSON.stringify(_this.nodeData[curNode.next[0].nodeIndex])
      );
      let node = undefined;
      switch (type) {
        case "signNode":
          node = nodeSvg.signNode({
            x: curNode.translate.x,
            y: curNode.translate.y + 80
          });
          break;
        case "reviewNode":
          node = nodeSvg.reviewNode({
            x: curNode.translate.x,
            y: curNode.translate.y + 80
          });
          break;
        case "sendNode":
          node = nodeSvg.sendNode({
            x: curNode.translate.x,
            y: curNode.translate.y + 80
          });
          break;
      }
      //新增节点与旧节点pre,next属性替换
      node.next = curNode.next;
      node.pre = nextNode.pre.filter(i => i.nodeIndex == nodeIndex);
      _this.nodeData.push(node);

      _this.nodeData[nodeIndex].next = [
        { nodeIndex: _this.nodeData.length - 1, pointPosition: "U" }
      ];
      _this.nodeData[curNode.next[0].nodeIndex].pre = _this.nodeData[
        curNode.next[0].nodeIndex
      ].pre.filter(i => i.nodeIndex != nodeIndex);
      _this.nodeData[curNode.next[0].nodeIndex].pre.push({
        nodeIndex: _this.nodeData.length - 1,
        pointPosition: "D"
      });

      //拿一下新节点的UD坐标,新增线
      let uppoint = this.nodeToline[_this.nodeData.length - 1].U;
      let downpoint = this.nodeToline[_this.nodeData.length - 1].D;

      //curSolidIndex 定位下当前节点的上一条线的具体index
      let curSolidIndex = 0;
      let newLineHead = _this.solidLineDict[nodeIndex][curSolidIndex][0];
      let solid = _this.solidLineDict[nodeIndex][curSolidIndex];
      solid[0] = downpoint;

      _this.$set(_this.solidLineDict, nodeIndex, [[newLineHead, uppoint]]);
      _this.$set(_this.solidLineDict, _this.nodeData.length - 1, [solid]);
    }
  }
};
</script>

<style lang="scss" scoped>
.rightmenu_main {
  background-color: #fffbf7;
  border: 1px solid #000000;
  z-index: 999;
  width: 180px;
  .rightmenu_child {
    background-color: #fffbf7;
    width: 174px;
    margin: 2px;
    border: 1px solid #fffbf7;
    height: 20px;
    &:hover {
      background-color: #b5bed6;
      border: 1px solid #08246b;
      height: 20px;
    }
  }
  .rightmenu_nor {
    background-color: #fffbf7;
    border: 1px solid #fffbf7;
    height: 20px;
    &:hover {
      background-color: #b5bed6;
      border: 1px solid #08246b;
      height: 20px;
    }
  }

  .rightmenu_select {
    background-color: #b5bed6;
    border: 1px solid #08246b;
    height: 20px;
  }
}

.rightmenu_check {
  font-size: 10px;
  font-weight: bold;
}

.round_nodetb {
  background-position: left 3px;
  width: 100%;
  height: 100%;
  border: 0px;
  padding: 0px;
  text-align: center;
  background-repeat: no-repeat;
}

.text {
  font-size: 12px;
  font-family: Helvetica, Arial, sans-serif;
  text-anchor: middle;
  cursor: default;
}

.node_main {
  z-index: 1;
}

.point_main {
  z-index: 5;
}

.line_normal {
  z-index: 2;
}

.round_nodetb {
  background-position: left 3px;
  width: 100%;
  height: 100%;
  border: 0px;
  padding: 0px;
  text-align: center;
  background-repeat: no-repeat;
}

.select_area {
  z-index: 99;
  position: absolute;
  background-color: #b5bed6;
  border: 1px solid #08246b;
  font-size: 1px;
  filter: Alpha(Opacity = 40);
  opacity: 0.4;
}
</style>